<?php
/**
 * 网关普通请求驱动
 */
namespace App\Winged\Backend\Http\Drivers;

use App\User;
use App\Winged\Backend\Http\HttpDriversInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\FileCookieJar;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Session;

class Common implements HttpDriversInterface
{
    protected $config;

    protected $client;

    function __construct($config)
    {
        $this->config = $config;
        $this->client = new Client([
            'base_uri'         => $this->config['host'],
            'connect_timeout' => $this->config['connect_timeout'],
            'timeout'          => $this->config['request_timeout'],
            'verify'           => $this->config['ssl_verify'],
            'http_errors'     => false,
            'debug'            => false
        ]);
    }

    /**
     * @param \App\Winged\Backend\Http\请求地址 $url
     * @param \App\Winged\Backend\Http\请求方法 $method
     * @param null                          $body
     * @param                               $headers
     * @return array
     */
    public function request($url, $method, $body = null, $headers)
    {
        $jar = $this->getCookieJar();
        info("request start url:{$url}, body:" , [$body]);
        $c = [] ;
        foreach ($jar as $item){
            info($item->getName(), [$item->getValue()]);
            $c [] = [
                'name' => $item->getName(),
                "isEmpty" => empty($item->getValue()),
            ];
        }
        try {
            $method             = strtoupper($method);
            $options            = [];
            $options['headers'] = $headers;
            $options['cookies'] =  $jar ;
            if (in_array(strtoupper($method), ['POST', 'PUT', 'PATH']) && !is_null($body)) {
                if (is_array($body) && isset($body ['_request_content_type'])) {
                    $_request_content_type = $body ['_request_content_type'];
                    unset($body['_request_content_type']);
                    if($_request_content_type == "body") {
                        $options['body'] = json_encode($body['body']);
                        $options['headers']['Content-Type'] = "application/json";
                    }
                    else{
                        $options [$_request_content_type] = $body;
                    }
                } else {
                    $options['form_params'] = $body;
                }
            }
            if (in_array(strtoupper($method), ['DELETE', 'GET']) && !is_null($body)) {
                $url .= '?' . http_build_query($body);
            }
            $response = $this->client->request($method, $url, $options);
            $contents = $response->getBody()->getContents();
            $status = $response->getStatusCode();

            info("response content:: ", [$contents]);
            info("response status:: {$status}");

            foreach($jar as $item) {
                info("response get::cookie:{$item->getName()}", [ $item->getValue() ]);
            }
            $this->handleCookieJar($jar);
            return [$status, $contents];
        } catch (RequestException $e) {
            // 暂时抛出
            throw $e;
        }
    }


    private function getCookieJar()
    {
        $token = token();
        if(is_null($token)) {
            return new CookieJar(false,[]);
        }
        $cookies = Redis::get($this->getCookieRedisKey());
        if(is_null($cookies)) {
            return new CookieJar(false,[]);
        }
        $cookies = unserialize($cookies) ;
        return $cookies ;
    }

    private function getCookieRedisKey()
    {
        return Session::get("uuid") ;
    }


    public function handleCookieJar(CookieJar $jar)
    {
        $ak = $jar->getCookieByName("access_token");
        $token = token();
        if(!is_null($ak) && !is_null($token) &&$ak->getValue() != $token) {
            token($ak->getValue());
            $user = Auth::user() ;
            if(!is_null($user)){
                $user->token = $ak->getValue() ;
                $user->save();
            }
        }
        $cookies = serialize($jar) ;
        $r = Redis::setex($this->getCookieRedisKey(), 120 * 60 ,$cookies);
    }


    public function errorHandle()
    {
        // TODO: Implement errorHandle() method.
    }


}
